// src/components/TencentMap.tsx
import React, { useEffect, useState, useRef } from 'react';
import { Box, Button, Dialog, Icon, List, Message, Search } from '@alifd/next';
import marker1 from '@/assets/marker1.png';
import { t } from '@lingui/macro';
import { observer } from 'mobx-react-lite';
import { apiLbs } from '@/services';
import useDenounce from '@/hooks/useDebounce';
import { strTransferNumber, deconstructionMapObj, arrTransferObj, strTransferArr } from '@/utils/util'
import * as _ from 'lodash';
import { toJS } from 'mobx';
import Styles from './MapModal.module.scss';

interface MapModelProps extends DialogProps {
  coord?: string;
  limitCity?: boolean;
  cityName: string;
  onPick: (coord?: string) => void;
  containerId?: string;
  visible: boolean;
}

interface RegionListItemProps {
  name: string;
  address: string;
  location: Array<number>;
  adcode: number;
}

interface PickerValueProps {
  lat: number;
  lng: number;
}

const TencentMap = (props: MapModelProps) => {
  const { coord, cityName, limitCity = true, visible, containerId, onPick, ...otherProps } = props;
  const [loading, setLoading] = useState<boolean>(false);
  const [search, setSearch] = useState<string>('');
  const [regionList, setRegionList] = useState<Array<RegionListItemProps>>([]);
  const [pickerValue, setPickerValue] = useState<PickerValueProps>();
  const [action, setAction] = useState<string>('');
  const [page, setPage] = useState<number>(0); // 页码

  const currentMoveStatusRef = useRef<boolean>(false); // 存储当前地图移动的状态
  const cityNameRef = useRef<string>(''); // 城市名称
  const mapRef = useRef(null); // 用于保存 map 对象
  const markerRef = useRef(null);  // 用于保存 marker 对象
  const lastItemRef = useRef(null); // 用于观察最后一个元素
  const lastUseFulLocationRef = useRef(null); // 用于记录最有一个有用坐标

  useEffect(() => {
    if (visible) {
      (async () => {
        const apiKey = await globalThis._mapsKey(); // 动态获取key
        // 加载腾讯地图 SDK
        const script = document.createElement('script');
        script.src = `https://map.qq.com/api/gljs?v=1.exp&key=${apiKey}`;
        script.charset = 'utf-8';
        script.onload = initMap; // 确保地图脚本加载完毕后调用 initMap
        document.body.appendChild(script);

        // 请求地址列表数据
        await initGetList(coord || '', true, true);

        // 在组件卸载时清理脚本
        return () => {
          document.body.removeChild(script);
        };
      })()
    }
    return () => {
      rest();
    };
  }, [visible]);

  /**
   * 初始化数据
   */
  function rest() {
    setSearch('');
    setRegionList([]);
    setPickerValue(null);
    setPage(0);
    currentMoveStatusRef.current = false;
    cityNameRef.current = '';
  }

  async function initGetList(location: string, init: boolean, isMove: boolean) {
    try {
      setLoading(true);
      const params = location;
      const { lat, lng } = strTransferNumber(params);
      const res = await apiLbs.lbsPlaceNearby({ center: strTransferArr(params), keyword: cityName });
      const { city, name, province } = res[0] || {};
      const currentCity = city || province;

      // 初始化
      if (init) {
        cityNameRef.current = city;
        setRegionList(res);
      }

      // 移动地图时
      if (isMove) {
        setRegionList(res);
      }

      // 超出当前城市  不允许后续操作
      if (limitCity && (!currentCity || currentCity !== cityNameRef.current)) {
        Message.warning({ content: t`当前位置超出【${cityNameRef.current}】范围，请重新选择`, duration: 5000 });
        const { _lat, _lng } = lastUseFulLocationRef.current;
        if (mapRef) {
          const map = mapRef.current;
          const center = new TMap.LatLng(_lng, _lat);
          map.setCenter(center);
          markerRef.current.setGeometries([
            {
              id: 'marker1',
              position: center,
              styleId: 'marker'
            }
          ]);

        }
        return;
      }
      lastUseFulLocationRef.current = { _lat: lat, _lng: lng };
      cityNameRef.current = currentCity;
      // search 默认值给上站点名称
      if (!init) await getRegionList(city || province, name, true, isMove);
    } catch (error) {
      throw error;
    } finally {
      setLoading(false);
    }
  }

  // 拖动地图防抖操作 避免过度请求
  const debouncedInitGetList = useDenounce(initGetList, 500);

  const initMap = () => {
    let location;
    if (coord) {
      location = strTransferNumber(coord);
    }
    const { lat, lng } = location;
    const center = new TMap.LatLng(lng, lat); // 设置地图中心点
    const map = new TMap.Map(containerId, {
      rotation: 0, // 设置地图旋转角度
      pitch: 0, // 设置俯仰角度（0~45）
      zoom: 14, // 设置地图缩放级别
      center: center, // 设置地图中心点坐标
    });

    mapRef.current = map;

    // 创建一个 Marker，初始化时放在中心
    const marker = new TMap.MultiMarker({
      map: map, // 将 marker 添加到地图上
      styles: { // 点标注的相关样式
        marker: new TMap.MarkerStyle({
          width: 34,
          height: 50,
          anchor: { x: 17, y: 25 },
          src: marker1,
          zIndex: 9999
        })
      },
      geometries: [
        {
          id: 'marker1',
          position: center, // 设置 marker 的初始位置
          styleId: 'marker'
        }
      ]
    });
    markerRef.current = marker;  // 保存 marker 引用

    // 监听地图的 'move' 事件，更新 marker 位置
    map.on('move', async () => {
      // 防止点击list列表触发地图移动事件
      if (currentMoveStatusRef.current) {
        currentMoveStatusRef.current = false;
        return;
      }

      const centerLocation = map.getCenter();  // 获取地图的中心点
      marker.setGeometries([
        {
          id: 'marker1',
          position: centerLocation,
          styleId: 'marker'
        }
      ]);

      setPickerValue(centerLocation);
      // 使用防抖后的函数
      debouncedInitGetList(deconstructionMapObj(centerLocation), false, true);
    });
  };

  const handleOK = () => {
    if (pickerValue) {
      onPick(pickerValue);
    } else {
      Message.error(t`请选择地址`);
      onPick();
    }
  };

  const handleOnSearch = (v) => {
    setSearch(v);
    setPage(0); // 重置页码
  };

  const handleOnClick = async () => {
    if (search && !loading) { // 确保不在加载状态时才触发请求
      try {
        setLoading(true);
        const cityName = cityNameRef.current;
        await getRegionList(cityName, search, false, false);
        setPage(prevPage => prevPage + 1); // 增加页码
      } catch (error) {
        console.error('Error fetching place search:', error.message);
      } finally {
        setLoading(false); // 确保无论是否成功，最终都会将 loading 设置为 false
      }
    }
  };

  async function getRegionList(city: string, keyword: string, init: boolean, isMove: boolean) {
    if (isMove) {
      return;
    }
    const res = await apiLbs.placeSearch({
      region: city,
      keyword: keyword,
      page: page, // 当前页码
    });
    if (init) {
      const { name, address, location } = res[0]
      const { lat, lng } = arrTransferObj(location)
      setAction(() => `${name}-${address}`)
      setPickerValue({ lat, lng });
    }
    if (page === 0) {
      setRegionList(res);
    } else {
      setRegionList((prevList) => [...prevList, ...res]);
    }
  }

  const handleRegionList = (result) => {
    const { name, address, location } = toJS(result);
    const { lat, lng } = arrTransferObj(location)
    setAction(() => `${name}-${address}`)
    setPickerValue({ lat, lng });
    currentMoveStatusRef.current = true;
    if (mapRef.current) {
      const map = mapRef.current;
      const center = new TMap.LatLng(lat, lng);
      map.setCenter(center);
      markerRef.current.setGeometries([
        {
          id: 'marker1',
          position: center,
          styleId: 'marker'
        }
      ]);
    }
  };

  // 滚动请求数据
  useEffect(() => {
    const observer = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting && !loading) { // 确保不在加载状态时才触发请求
        handleOnClick();
      }
    },
      { threshold: 0.1 } // 设置阈值，确保在元素进入视口 10% 时触发
    );

    if (lastItemRef.current && regionList.length > 19) {
      observer.observe(lastItemRef.current);
    }

    return () => {
      if (lastItemRef.current) {
        observer.unobserve(lastItemRef.current);
      }
    };
  }, [lastItemRef, loading, handleOnClick]); // 添加 handleOnClick 作为依赖项

  return (
    <Dialog
      v2
      title={(
        <Box direction='row' wrap={false}>
          {t`选择地点`}
          <div style={{ marginLeft: 20 }}>
            <Icon className="iconfont icon-location" size={18} style={{ color: 'red' }} />
            <span>{cityNameRef.current}</span>
          </div>
        </Box>
      )}
      centered
      width="70%"
      height="100vh"
      onOk={handleOK}
      visible={visible}
      {...otherProps}
    >
      <Box direction='row' wrap={false}>
        <Search
          placeholder={t`搜索地点`}
          key="2"
          shape="simple"
          hasClear
          onChange={(value) => handleOnSearch(value)}
          onSearch={handleOnClick}
          value={search}
          style={{ width: '100%', marginBottom: 10 }}
        />
        {search && <Button
          type="primary"
          text
          onClick={handleOnClick}
          style={{ marginLeft: 10 }}
        >
          <span style={{ fontSize: 16, fontWeight: 500, marginTop: 5 }}>
            {t`搜索`}
          </span>
        </Button>}
      </Box>
      <div id={containerId} className={Styles.map_container} ></div>
      <div className={Styles.region_list}>
        <List
          loading={loading}
          size="small"
          style={{ height: 300 }}
          dataSource={regionList}
          renderItem={(item, i) => (
            <List.Item
              onClick={() => handleRegionList(item)}
              key={i}
              extra={action === `${item.name}-${item.address}` ? <Icon type="success" style={{ color: 'rgb(52, 119, 246)' }} /> : null}
              title={<span style={{ fontWeight: 500 }}>{item.name}</span>}
              media={<Icon size={14} style={{ marginTop: 5 }} type="search" />}
            >
              <span style={{ fontSize: 13 }}>{item.address}</span>
            </List.Item>
          )}
          footer={
            regionList.length > 0 && (
              <div ref={lastItemRef} style={{ height: 1, marginBottom: 20 }} />
            )
          }
        />
      </div>
    </Dialog>
  );
};

export default observer(TencentMap);
